package com.wjw.utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Writer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.text.DecimalFormat;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * @desc 文件操作类
 * @author wjw
 * @date 2016年11月21日下午2:35:44
 */
public final class FileUtil{
	
    /**
     * 日志对象
     */
    protected static Logger log = LoggerFactory.getLogger(FileUtil.class);
	
	/** 创建目录，如果是文件则创建父目录  */
	public static boolean createFatherFolder(String path) {
		try {
			if(path.substring(path.lastIndexOf("\\")).contains(".")){//是否是文件
				path = path.substring(0,path.lastIndexOf("\\"));
			}
			File folderPath = new File(path);
			if (!folderPath.exists()) {
				folderPath.mkdir();
			}
			return true;
		} catch (Exception e) {
			log.error("创建父目录操作出错");
			e.printStackTrace();
			return false;
		}
	}

	/** 新建文件 */
	public static boolean createFile(String filePathAndName, String fileContent) {
		try {
			File myFile = new File(filePathAndName);
			createFatherFolder(filePathAndName);
			FileWriter fw = new FileWriter(myFile);
			PrintWriter pw = new PrintWriter(fw);
			pw.println(fileContent);
			pw.close();
			fw.close();
			return true;
		} catch (Exception e) {
			log.error("新建文件出错");
			e.printStackTrace();
			return false;
		}

	}
	
	/** 指定编码写入文件 */
	public static boolean write(String filePathAndName, String fileContent,String encoding) {
		try {
			File myFile = new File(filePathAndName);
			createFatherFolder(filePathAndName);
			Writer w =  initWriter(myFile, encoding, false);
			PrintWriter pw = new PrintWriter(w);
			pw.println(fileContent);
			pw.close();
			w.close();
			return true;
		} catch (Exception e) {
			log.error("新建文件出错");
			e.printStackTrace();
			return false;
		}

	}

	/** 删除文件或目录  递归删除子文件或目录 */
	public static void delFile(String filePath) {
		File file = new File(filePath);
		if (file.isDirectory()) {
			String[] files = file.list();
			if(files.length > 0){
				for (String path : files) {
					delFile(file.getAbsolutePath()+File.separator+path);
				}
			}
		}
		file.delete();//删除文件或目录
	}
	
	/** 复制单个文件到指定目录下 */
	public static boolean copyFile(String oldPath, String newFolder) {
			return copyFile(oldPath, new File(newFolder + File.separator + oldPath.substring(oldPath.lastIndexOf(File.separator))));
	}
	
	/** 复制单个文件到指定文件  */
	public static boolean copyFile(String oldPath, File newFile) {
		try {
			int byteread = 0;
			File oldfile = new File(oldPath);
			if (oldfile.exists()) { // 文件存在时
				createFatherFolder(newFile.getAbsolutePath());//创建目录
				InputStream inStream = new FileInputStream(oldPath); // 读入原文件
				FileOutputStream fs = new FileOutputStream(newFile);
				byte[] buffer = new byte[1444];
				while ((byteread = inStream.read(buffer)) != -1) {
					fs.write(buffer, 0, byteread);
				}
				fs.flush();
				fs.close();
				inStream.close();
			}
			return true;
		} catch (Exception e) {
			log.error("复制单个文件操作出错");
			e.printStackTrace();
			return false;
		}
	}

	/** 复制整个目录 */
	public static boolean copyFolder(String oldPath, String newPath) {
		oldPath = oldPath.endsWith(File.separator)? oldPath.substring(0, oldPath.length()-1):oldPath;
		newPath = newPath.endsWith(File.separator)? newPath.substring(0, newPath.length()-1):newPath;
		try {
			(new File(newPath)).mkdirs(); // 如果文件夹不存在 则建立新文件夹
			File a = new File(oldPath);
			String[] file = a.list();
			File temp = null;
			for (int i = 0; i < file.length; i++) {
				
				temp = new File(oldPath + File.separator + file[i]);
				if (temp.isFile()) {
					FileInputStream input = new FileInputStream(temp);
					FileOutputStream output = new FileOutputStream(newPath + File.separator + (temp.getName()).toString());
					byte[] b = new byte[1024 * 5];
					int len;
					while ((len = input.read(b)) != -1) {
						output.write(b, 0, len);
					}
					output.flush();
					output.close();
					input.close();
				}
				if (temp.isDirectory()) {// 如果是子文件夹
					copyFolder(oldPath + File.separator + file[i], newPath + File.separator + file[i]);
				}
			}
			return true;
		} catch (Exception e) {
			log.error("复制整个文件夹内容操作出错");
			e.printStackTrace();
			return false;
		}

	}

	/** 移动目录或文件到指定目录下  */
	public static void moveFolder(String oldPath, String newPath) {
		if(!new File(oldPath).isDirectory()){
			copyFile(oldPath, newPath);
		}else{
			copyFolder(oldPath, newPath);
		}
		delFile(oldPath);

	}

	/** 重命名文件 oldFile newFile *注意 目录重命名有问题  */
	public static void renameFolder(String oldFolder, String newFolder) {
		try {
			File file = new File(oldFolder);
			file.renameTo(new File(newFolder));
		} catch (Exception e) {
			log.error("重命名文件 出错");
			e.printStackTrace();
		}
	}

	/** 计算文件大小 */
	@SuppressWarnings("resource")
	public static long getFileSize(File f) throws Exception {// 取得文件大小
		long s = 0;
		if (f.exists()) {
			FileInputStream fis = null;
			fis = new FileInputStream(f);
			s = fis.available();
		} else {
			f.createNewFile();
			log.error("文件不存在");
		}
		return s;
	}

	
	public long folderCount;
	public long flieCount;
	public long totalSize;
	/** 递归计算文件夹大小  */
	public void getFolderSize(File f) throws Exception {
		File flist[] = f.listFiles();
		for (File fc : flist) {
			if (fc.isDirectory()) {
				folderCount++;
				getFolderSize(fc);
			} else {
				flieCount++;
				totalSize += fc.length();
			}
		}
	}

	public String FormetFileSize(long fileS) {// 转换文件大小
		DecimalFormat df = new DecimalFormat("#.000");
		String fileSizeString = "";
		if (fileS < 1024) {
			fileSizeString = df.format((double) fileS) + "B";
		} else if (fileS < 1048576) {
			fileSizeString = df.format((double) fileS / 1024) + "KB";
		} else if (fileS < 1073741824) {
			fileSizeString = df.format((double) fileS / 1048576) + "MB";
		} else {
			fileSizeString = df.format((double) fileS / 1073741824) + "GB";
		}
		return fileSizeString;
	}
	
	private static Writer initWriter(final File file, final Object encoding, final boolean append) throws IOException {
        if (file == null) {
            throw new NullPointerException("File is missing");
        }
        if (encoding == null) {
            throw new NullPointerException("Encoding is missing");
        }
        final boolean fileExistedAlready = file.exists();
        OutputStream stream = null;
        Writer writer = null;
        try {
            stream = new FileOutputStream(file, append);
            if (encoding instanceof Charset) {
                writer = new OutputStreamWriter(stream, (Charset)encoding);
            } else if (encoding instanceof CharsetEncoder) {
                writer = new OutputStreamWriter(stream, (CharsetEncoder)encoding);
            } else {
                writer = new OutputStreamWriter(stream, (String)encoding);
            }
        } catch (final IOException ex) {
        	writer.close();
        	stream.close();
            if (fileExistedAlready == false) {
            	delFile(file.getAbsolutePath());
            }
            throw ex;
        } catch (final RuntimeException ex) {
        	writer.close();
        	stream.close();
            if (fileExistedAlready == false) {
            	delFile(file.getAbsolutePath());
            }
            throw ex;
        }
        return writer;
    }

	public static void main(String args[]) {
		FileUtil g = new FileUtil();
		long startTime = System.currentTimeMillis();
		try {
			String path = "D:\\repository";
			File ff = new File(path);
			g.getFolderSize(ff);
			System.out.println(g.FormetFileSize(g.totalSize));
			System.out.println(g.flieCount);
			System.out.println(g.folderCount);

		} catch (Exception e) {
			e.printStackTrace();
		}
		long endTime = System.currentTimeMillis();
		log.info("总共花费时间为：" + (endTime - startTime) + "毫秒...");
	}
}
